package cool.taomu.software.fig.core

import cool.taomu.software.fig.classloader.FigClassLoaderManage
import cool.taomu.software.fig.crypto.Base64
import cool.taomu.software.fig.entity.FigData
import cool.taomu.software.fig.mqtt.client.paho.entity.SenderEntity
import cool.taomu.software.fig.objectpool.ObjectPoolFactory
import cool.taomu.software.fig.reflect.ReflectUtils
import cool.taomu.software.fig.utils.FigGsonUtils
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.Method
import java.util.List
import java.util.concurrent.BlockingQueue
import org.eclipse.paho.client.mqttv3.MqttMessage
import org.slf4j.LoggerFactory

class MqttMessageProcessing implements Runnable {
    static val LOG = LoggerFactory.getLogger(MqttMessageProcessing);
    String zlassName;
    MqttMessage message;
    String topic;
    String methodName;
    BlockingQueue<SenderEntity> queue;

    new(String zlassName, MqttMessage message, String topic, String methodName, BlockingQueue<SenderEntity> queue) {
        this.zlassName = zlassName;
        this.message = message;
        this.topic = topic;
        this.methodName = methodName;
        this.queue = queue;
    }

    def void callClient(Method client, FigData<?> data,
        Object instance) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        if (client.getReturnType().equals(void)) {
            client.invoke(instance, data);
        } else {
            val Object result = client.invoke(instance, data);
            if (result instanceof SenderEntity) {
                queue.offer(result);
            } else if (result instanceof SenderEntity[]) {
                for (SenderEntity entity : result) {
                    queue.offer(entity);
                }
            } else {
                if (result instanceof List) {
                    for (Object entity : result) {
                        if (entity instanceof SenderEntity) {
                            queue.offer(entity);
                        }
                    }
                }
            }
        }
    }

    def void callClient(Method client, String topic, MqttMessage message,
        Object instance) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        if (client.getReturnType().equals(void)) {
            client.invoke(instance, topic, message);
        } else {
            val Object result = client.invoke(instance, topic, message);
            if (result instanceof SenderEntity) {
                queue.offer(result);
            } else if (result instanceof SenderEntity[]) {
                for (SenderEntity entity : result) {
                    queue.offer(entity);
                }
            } else {
                if (result instanceof List) {
                    for (Object entity : result) {
                        if (entity instanceof SenderEntity) {
                            queue.offer(entity);
                        }
                    }
                }
            }
        }
    }

    override run() {
        try {
            if (zlassName !== null && !"".equals(zlassName)) {
                var fig = new FigClassLoaderManage();
                LOG.debug("处理的callback为：{}", zlassName);
                var Class<?> zlass = fig.getClassLoader(zlassName);
                try (val pool = ObjectPoolFactory.getInstance().borrowObject(zlass as Class<Object>)) {
                    var byte[] base64Decode = new Base64(message.getPayload()).decode();
                    var Object instance = pool.getInstance();
                    try {
                        var FigData<?> fdata = FigGsonUtils.toObject(new String(base64Decode, "UTF-8"), FigData);
                        var Method client = ReflectUtils.getMethod(zlass, methodName, #[FigData]);
                        if (client === null) {
                            throw new UnknownError("参数为FigData的方法没有找到");
                        }
                        callClient(client, fdata, instance);
                    } catch (Exception ex) {
                        LOG.info("执行String,MqttMessage参数的方法:{}", ex.getMessage());
                        message.setPayload(base64Decode);
                        val Method client = ReflectUtils.getMethod(zlass, methodName, #[String, MqttMessage]);
                        callClient(client, topic, message, instance);
                    }
                }
            }
        } catch (Exception ex) {
            Thread.currentThread().interrupt();
            LOG.error("Runnable中出现了错误", ex);
        }
    }

}
